package com.nd.sdp.android.configuration.compiler;

import android.support.annotation.Keep;

import com.google.common.collect.Multimap;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;

import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;

class ServicePoolGenerator {

    private static final ClassName SERVICE_POOL_IMPL = ClassName.get("com.nd.sdp.android.configuration.internal", "ServicePool");
    private static final ClassName SERVICE_POOL = ClassName.get("com.nd.sdp.android.configuration.internal", "IServicePool");

    static JavaFile process(Multimap<TypeElement, TypeElement> result) {
        ParameterizedTypeName listTypeName = ParameterizedTypeName.get(List.class, Class.class);
        ClassName className = ClassName.get(Class.class);
        ClassName hashMapClassName = ClassName.get(HashMap.class);
        ParameterizedTypeName hashMap = ParameterizedTypeName.get(hashMapClassName, className, listTypeName);
        ClassName mapUtils = ClassName.get("com.nd.sdp.android.configuration.utils", "MapUtils");
        FieldSpec mClassListMap = FieldSpec.builder(hashMap, "mClassListMap", Modifier.PRIVATE)
                .build();
        MethodSpec.Builder initBuilder = MethodSpec.methodBuilder("init")
                .addModifiers(Modifier.PRIVATE)
                .returns(TypeName.VOID)
                .addStatement("mClassListMap=new $T()", hashMap);
        for (TypeElement interfaceElement : result.keySet()) {
            ClassName interfaceClass = ClassName.get(interfaceElement);
            Collection<TypeElement> impleElements = result.get(interfaceElement);
            for (TypeElement implClassElement : impleElements) {
                ClassName implClass = ClassName.get(implClassElement);
                initBuilder.addStatement("$T.joinMapList($T.class,$T.class,mClassListMap)", mapUtils, interfaceClass, implClass);
            }
        }
        MethodSpec init = initBuilder.build();
        MethodSpec getBeanConfiguration = MethodSpec.methodBuilder("getBeanConfiguration")
                .addModifiers(Modifier.PUBLIC)
                .returns(hashMap)
                .addAnnotation(Override.class)
                .beginControlFlow("if(mClassListMap==null)")
                .addStatement("init()")
                .endControlFlow()
                .addStatement("return mClassListMap")
                .build();
        TypeSpec injectClass = TypeSpec.classBuilder(SERVICE_POOL_IMPL.simpleName())
                .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
                .addSuperinterface(SERVICE_POOL)
                .addField(mClassListMap)
                .addMethod(init)
                .addAnnotation(Keep.class)
                .addMethod(getBeanConfiguration)
                .build();
        return JavaFile.builder(SERVICE_POOL_IMPL.packageName(), injectClass).build();
    }

}
